定义三个 unordered_map,两个 unordered_map 的键和值都是 int 类型,分别存被访问的次数定义名字为 mp 和是在什么时候存进来的定义名字为 jl,第三个 unordered_map 的键为 int 类型,而值为 vector 数组,用来存访问次数为键的内存页是几定义名字为 se。
定义 c 为需要访问的虚拟内存页的编号,再定义一个 minn 表示现在最少的访问次数。
如果要访问的内存页存在也就是 mp.count(c) 为一,那么让我们的答案加一,然后把 se 里的数组里的 c 删除,接着把 c 加入到 se 的键为这次操作后 c 被访问的次数的数组里,然后判断一下在这次操作后原本 se 的键为 minn 的数组大小是否为零,如果为零则代表 c 原本是这个数组里唯一的元素,而 c 的访问次数增加后,这个数组里就没有元素了,也就是最少的访问次数现在不是 minn 了而是 minn 加上一,我们让 minn 加一。
如果要访问的内存页不存在,则先判断一下现在 mp 里键的数量是否小于 n:
如果小于 n,则把 mpc 赋值为一,然后将 jlc 赋值为现在是第几个操作,然后在 se 里键为一的数组里加入 c,最后把 minn 赋值为一,因为 c 是刚刚加入的,所以只被访问了一次,是最少的访问次数。
如果不小于 n 则把 se 里键为 minn 的数组里的第一个值删除并把 c 加入 se 里键为一的数组里。
代码:
#include<bits/stdc++.h> usingnamespace std; #define LL long long #define itn int #define ull unsigned long long int n,m,ans=0; unordered_map<int,int>mp;// 被访问的次数 unordered_map<int,int>jl;// 是在什么时候存进来的 unordered_map<int,vector<int> >se;// 访问次数,是什么 int minn=1e9;// 最少的访问次数 intmain(){ ios::sync_with_stdio(0); cin.tie(0),cout.tie(0); cin>>n>>m; jl[int(1e9+1)]=m+1; int c; for(int i=1;i<=m;i++){ cin>>c; if(mp.count(c)){ ans++; auto it=find(se[mp[c]].begin(),se[mp[c]].end(),c); se[mp[c]].erase(it); if(se[minn].size()==0)minn++; mp[c]++; se[mp[c]].push_back(c); } else{ if(mp.size()<n){ mp[c]=1; jl[c]=i; se[mp[c]].push_back(c); minn=1; } else{ int sanc=1e9+1; auto it=se.begin(); vector<int>sz(se[minn]); sanc=sz[0]; auto itt=find(se[mp[sanc]].begin(),se[mp[sanc]].end(),sanc); se[mp[sanc]].erase(itt); if(se[mp[sanc]].size()==0)se.erase(mp[sanc]); mp.erase(sanc); jl.erase(sanc); mp[c]=1; jl[c]=i; minn=1; se[mp[c]].push_back(c); } } } cout<<ans; return0; }